﻿#region Directives

using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.IO;

#endregion Directives

namespace ConnectIntegrationHub.WebService.Common
{
    public class ZipFiles
    {
        #region Public Static Methods

        public static void extract(String fileName, String outputFolderName)
        {
            ZipFile zf = null;
            try
            {
                var fs = File.OpenRead(fileName);
                zf = new ZipFile(fs);
                foreach (ZipEntry zipEntry in zf)
                {
                    if (!zipEntry.IsFile)
                    {
                        continue;
                    }

                    var entryFileName = zipEntry.Name;
                    var buffer = new Byte[4096];

                    var zipStream = zf.GetInputStream(zipEntry);

                    var fullZipToPath = Path.Combine(outputFolderName, entryFileName);
                    var directoryName = Path.GetDirectoryName(fullZipToPath);
                    
                    if (directoryName.Length > 0)
                    {
                        Directory.CreateDirectory(directoryName);
                    }
                    using (FileStream streamWriter = File.Create(fullZipToPath))
                    {
                        StreamUtils.Copy(zipStream, streamWriter, buffer);
                    }
                }
            }
            finally
            {
                if (zf != null)
                {
                    zf.IsStreamOwner = true;
                    zf.Close();
                }
            }
        }

        public static void create(String outputPath, String folderName)
        {
            var fs = File.Create(outputPath);
            
            var zipStream = new ZipOutputStream(fs);
            zipStream.SetLevel(3);

            var folderOffset = folderName.Length + (folderName.EndsWith("\\") ? 0 : 1);

            compress(folderName, zipStream, folderOffset);

            zipStream.IsStreamOwner = true;
            zipStream.Close();
        }

        #endregion Public Static Methods

        #region Private Static Methods
        
        private static void compress(String path, ZipOutputStream zipStream, Int32 folderOffset)
        {
            foreach (String filename in Directory.GetFiles(path))
            {
                var fi = new FileInfo(filename);

                String entryName = filename.Substring(folderOffset);
                entryName = ZipEntry.CleanName(entryName);
                ZipEntry newEntry = new ZipEntry(entryName);
                newEntry.DateTime = fi.LastWriteTime;

                newEntry.Size = fi.Length;
                zipStream.PutNextEntry(newEntry);

                var buffer = new Byte[4096];
                using (var streamReader = File.OpenRead(filename))
                {
                    StreamUtils.Copy(streamReader, zipStream, buffer);
                }
                zipStream.CloseEntry();
            }

            foreach (var folder in Directory.GetDirectories(path))
            {
                compress(folder, zipStream, folderOffset);
            }
        }
        
        #endregion Private Static Methods
    }
}